<?php

namespace App\Trip\Orders\BookOrders\Train;

use App\Models\Train\Stations\TrainStation;
use App\Trip\Orders\BookOrders\Params\AbstractParam\TripParam;
use App\Trip\Train\Providers\PiaoChi\TrainQuery;
use App\Trip\Train\Seat\SeatInventory;
use App\Trip\Train\Seat\Seats;
use App\Trip\Train\TrainInfo\TrainInfo;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;

class TrainStationTicket
{
    private TrainInfo     $train_info;
    private TripParam     $train_param;
    private ?TrainStation $from_station;
    private ?TrainStation $to_station;
    private mixed         $seats;
    private int           $retry = 0;

    /**
     * @throws Exception
     */
    public function __construct(TripParam $train_param)
    {
        $this->train_param  = $train_param;
        $this->train_info   = $this->train_param->getTripInfo();
        $this->from_station = $this->train_param->getFrom();
        $this->to_station   = $this->train_param->getTo();
    }

    /**
     * @throws Exception
     */
    public function TrainInfo(): TrainInfo
    {
        return $this->train_info;
    }

    /**
     * @throws Exception|GuzzleException
     */
    public function getSeat(string $seat_name, bool $ignore_inventory = false): Seats
    {
        if ($this->train_info->isDepart()) {
            throw new Exception("列车已发车", 61001);
        }
        $this->queryTicket();
        // 验证坐席库存
        $seatInventory = new SeatInventory($this->train_info->getTrainCode(),
            $this->train_param->getFromCode(),
            $this->train_param->getToCode(),
            $seat_name);
        if (!($seatInventory->getInventory() > 0)) {
            if (!$ignore_inventory) {
                throw new Exception("余票不足", 60001);
            }
        }
        $current_seat = collect($this->getSeats())->where('seat_name', $seat_name)->first();
        if (!$current_seat) {
            throw new Exception("该车次没有座位：{$seat_name}");
        }
        return new Seats([
            "train_code"        => $this->train_info->getTrainCode(),
            "seat_name"         => $current_seat["seat_name"],
            "seat_price"        => $current_seat['seat_price'],
            "seat_inventory"    => $current_seat['seat_inventory'],
            "from_station_code" => $this->from_station->getStationCode(),
            "to_station_code"   => $this->to_station->getStationCode(),
        ]);
    }

    /**
     * @throws GuzzleException
     * @throws Exception
     */
    public function queryTicket(): self
    {
        try {
            $param             = [
                "from_station"      => $this->from_station->getStationName(),
                "from_station_code" => $this->from_station->getStationCode(),
                "to_station"        => $this->to_station->getStationName(),
                "to_station_code"   => $this->to_station->getStationCode(),
                "train_date"        => $this->train_info->getTrainDate(),
            ];
            $query             = new TrainQuery();
            $res               = $query->queryTicket($param, true);
            $train_seat_ticket = collect($res["train_numbers"])->where('train_code', $this->train_info->getTrainCode())->first();
            $this->retry       = 0;
        } catch (Exception $e) {
            $sleep = 10000;
            Log::error("TrainStationTicket->火车票查询失败:retry:{$this->retry} - ".$e->getMessage()."--".$e->getFile()."--".$e->getLine());
            if ($this->retry > 3) {
                throw new Exception(__("火车票查询失败").__("请稍后重试").$e->getMessage(), 502);
            }
            $this->retry++;
            usleep($this->retry * $sleep);
            $this->queryTicket();
        }
        // 有可能 3次查询均未获取结果
        if (!isset($train_seat_ticket) || !isset($train_seat_ticket['seats'])) {
            throw new Exception(__("火车票查询失败").__("请稍后重试"), 502);
        }
        $this->seats = $train_seat_ticket['seats'];
        return $this;
    }

    private function getSeats(): array
    {
        return $this->seats;
    }


}